"""
人脸识别API接口
遵循开发规范，处理HTTP请求并返回标准格式
"""

from fastapi import APIRouter, HTTPException, File, UploadFile, Form
from typing import List, Optional
import json

from schemas.face import (
    FaceAddRequest,
    FaceAddResponse,
    FaceCompareRequest,
    FaceCompareResponse,
    FaceSearchRequest,
    FaceSearchResult,
    FaceSearchResponse,
    FaceDetectRequest,
    FaceDetectResponse,
    FaceDetectResult,
    FaceDeleteRequest,
    FaceRect,
)
from services.face_service import FaceService
from utils.api_response import ApiResponseHelper
from utils.image_utils import ImageUtils
from utils.logger import app_logger

# 创建路由
router = APIRouter(prefix="/api/v1/face", tags=["人脸识别"])

# Service实例
face_service = FaceService()


@router.post("/add")
async def add_face(request: FaceAddRequest):
    """
    添加人脸（Base64方式）

    - **person_id**: 人员ID
    - **person_name**: 人员姓名
    - **image**: 图片base64编码
    - **meta_info**: 扩展信息（可选）
    """
    try:
        app_logger.info(f"收到人脸添加请求(Base64): person_id={request.person_id}")

        # 调用Service
        success, result = face_service.add_face(
            person_id=request.person_id,
            person_name=request.person_name,
            image_base64=request.image,
            meta_info=request.meta_info,
        )

        if not success:
            return ApiResponseHelper.error(msg=result, code=500)

        # 转换为Schema
        face_dto = result
        response = FaceAddResponse(
            face_id=face_dto.face_id,
            person_id=face_dto.person_id,
            person_name=face_dto.person_name,
            quality=face_dto.quality_score,
            face_rect=FaceRect(**face_dto.face_rect),
        )

        return ApiResponseHelper.success(data=response, msg="人脸添加成功")

    except Exception as e:
        app_logger.error(f"人脸添加接口异常: {e}", exc_info=True)
        return ApiResponseHelper.internal_error(msg="系统错误")


@router.post("/add-file")
async def add_face_file(
    file: UploadFile = File(..., description="人脸图片文件"),
    person_id: str = Form(..., description="人员ID"),
    person_name: str = Form(..., description="人员姓名"),
    meta_info: Optional[str] = Form(None, description="扩展信息(JSON字符串)"),
):
    """
    添加人脸（文件上传方式）

    - **file**: 图片文件（支持jpg、png等格式）
    - **person_id**: 人员ID
    - **person_name**: 人员姓名
    - **meta_info**: 扩展信息（可选，JSON字符串格式）

    示例 curl 命令：
    ```bash
    curl -X POST "http://localhost:8001/api/v1/face/add-file" \\
      -F "file=@face.jpg" \\
      -F "person_id=001" \\
      -F "person_name=张三" \\
      -F 'meta_info={"department":"技术部"}'
    ```
    """
    try:
        app_logger.info(
            f"收到人脸添加请求(文件上传): person_id={person_id}, filename={file.filename}"
        )

        # 验证文件类型
        if not file.content_type or not file.content_type.startswith("image/"):
            return ApiResponseHelper.error(msg="文件类型错误，请上传图片文件", code=400)

        # 读取文件内容
        file_bytes = await file.read()
        if not file_bytes:
            return ApiResponseHelper.error(msg="文件内容为空", code=400)

        # 转换为cv2图像
        img = ImageUtils.bytes_to_cv2(file_bytes)
        if img is None:
            return ApiResponseHelper.error(msg="图片解析失败", code=400)

        # 将图像转换为base64（复用现有Service逻辑）
        image_base64 = ImageUtils.cv2_to_base64(img)
        if not image_base64:
            return ApiResponseHelper.error(msg="图片转换失败", code=500)

        # 解析meta_info
        parsed_meta_info = None
        if meta_info:
            try:
                parsed_meta_info = json.loads(meta_info)
            except json.JSONDecodeError:
                return ApiResponseHelper.error(
                    msg="meta_info格式错误，需要JSON字符串", code=400
                )

        # 调用Service
        success, result = face_service.add_face(
            person_id=person_id,
            person_name=person_name,
            image_base64=image_base64,
            meta_info=parsed_meta_info,
        )

        if not success:
            return ApiResponseHelper.error(msg=result, code=500)

        # 转换为Schema
        face_dto = result
        response = FaceAddResponse(
            face_id=face_dto.face_id,
            person_id=face_dto.person_id,
            person_name=face_dto.person_name,
            quality=face_dto.quality_score,
            face_rect=FaceRect(**face_dto.face_rect),
        )

        return ApiResponseHelper.success(data=response, msg="人脸添加成功")

    except Exception as e:
        app_logger.error(f"人脸添加接口异常(文件上传): {e}", exc_info=True)
        return ApiResponseHelper.internal_error(msg="系统错误")


@router.post("/compare")
async def compare_faces(request: FaceCompareRequest):
    """
    人脸比对（1:1）

    - **image_a**: 图片A的base64编码
    - **image_b**: 图片B的base64编码
    """
    try:
        app_logger.info("收到人脸比对请求")

        # 调用Service
        result_dto = face_service.compare_faces(
            image_a_base64=request.image_a, image_b_base64=request.image_b
        )

        if not result_dto:
            return ApiResponseHelper.error(msg="人脸比对失败", code=500)

        # 转换为Schema
        response = FaceCompareResponse(
            similarity=result_dto.similarity,
            is_match=result_dto.is_match,
            threshold=result_dto.threshold,
        )

        return ApiResponseHelper.success(data=response, msg="比对成功")

    except Exception as e:
        app_logger.error(f"人脸比对接口异常: {e}", exc_info=True)
        return ApiResponseHelper.internal_error(msg="系统错误")


@router.post("/search")
async def search_face(request: FaceSearchRequest):
    """
    人脸识别（1:N）

    - **image**: 待识别图片的base64编码
    - **top_k**: 返回前K个结果（默认5）
    - **threshold**: 相似度阈值（默认0.7）
    """
    try:
        app_logger.info(
            f"收到人脸识别请求: top_k={request.top_k}, threshold={request.threshold}"
        )

        # 调用Service
        results_dto = face_service.search_face(
            image_base64=request.image, top_k=request.top_k, threshold=request.threshold
        )

        # 转换为Schema
        results = [
            FaceSearchResult(
                face_id=dto.face_id,
                person_id=dto.person_id,
                person_name=dto.person_name,
                similarity=dto.similarity,
            )
            for dto in results_dto
        ]

        response = FaceSearchResponse(face_count=1 if results else 0, results=results)

        return ApiResponseHelper.success(data=response, msg="识别成功")

    except Exception as e:
        app_logger.error(f"人脸识别接口异常: {e}", exc_info=True)
        return ApiResponseHelper.internal_error(msg="系统错误")


@router.post("/search-file")
async def search_face_file(
    file: UploadFile = File(..., description="待识别的图片文件"),
    top_k: int = 5,
    threshold: float = 0.7,
):
    """
    人脸识别（文件上传方式）

    - **file**: 待识别的图片文件
    - **top_k**: 返回前K个结果（默认5，范围1-20）
    - **threshold**: 相似度阈值（默认0.7，范围0.0-1.0）

    示例 curl 命令：
    ```bash
    curl -X POST "http://localhost:8001/api/v1/face/search-file" \\
      -F "file=@face.jpg" \\
      -F "top_k=5" \\
      -F "threshold=0.7"
    ```
    """
    try:
        app_logger.info(
            f"收到人脸识别请求(文件上传): top_k={top_k}, threshold={threshold}, filename={file.filename}"
        )

        # 验证参数
        if not 1 <= top_k <= 20:
            return ApiResponseHelper.error(msg="top_k 范围应为 1-20", code=400)
        if not 0.0 <= threshold <= 1.0:
            return ApiResponseHelper.error(msg="threshold 范围应为 0.0-1.0", code=400)

        # 验证文件类型
        if not file.content_type or not file.content_type.startswith("image/"):
            return ApiResponseHelper.error(msg="文件类型错误，请上传图片文件", code=400)

        # 读取文件内容
        file_bytes = await file.read()
        if not file_bytes:
            return ApiResponseHelper.error(msg="文件内容为空", code=400)

        # 转换为cv2图像
        img = ImageUtils.bytes_to_cv2(file_bytes)
        if img is None:
            return ApiResponseHelper.error(msg="图片解析失败", code=400)

        # 将图像转换为base64
        image_base64 = ImageUtils.cv2_to_base64(img)
        if not image_base64:
            return ApiResponseHelper.error(msg="图片转换失败", code=500)

        # 调用Service
        results_dto = face_service.search_face(
            image_base64=image_base64, top_k=top_k, threshold=threshold
        )

        # 转换为Schema
        results = [
            FaceSearchResult(
                face_id=dto.face_id,
                person_id=dto.person_id,
                person_name=dto.person_name,
                similarity=dto.similarity,
            )
            for dto in results_dto
        ]

        response = FaceSearchResponse(face_count=len(results), results=results)

        return ApiResponseHelper.success(data=response, msg="识别成功")

    except Exception as e:
        app_logger.error(f"人脸识别接口异常(文件上传): {e}", exc_info=True)
        return ApiResponseHelper.internal_error(msg="系统错误")


@router.post("/detect")
async def detect_faces(request: FaceDetectRequest):
    """
    人脸检测

    - **image**: 图片base64编码
    """
    try:
        app_logger.info("收到人脸检测请求")

        # 调用Service
        faces_dto = face_service.detect_faces(request.image)

        # 转换为Schema
        faces = [
            FaceDetectResult(
                face_rect=FaceRect(**dto.face_rect),
                landmarks=dto.landmarks,
                quality=dto.quality,
                angle=dto.angle,
            )
            for dto in faces_dto
        ]

        response = FaceDetectResponse(face_count=len(faces), faces=faces)

        return ApiResponseHelper.success(data=response, msg="检测成功")

    except Exception as e:
        app_logger.error(f"人脸检测接口异常: {e}", exc_info=True)
        return ApiResponseHelper.internal_error(msg="系统错误")


@router.delete("/delete")
async def delete_face(request: FaceDeleteRequest):
    """
    删除人脸

    - **face_id**: 人脸ID
    """
    try:
        app_logger.info(f"收到人脸删除请求: face_id={request.face_id}")

        # 调用Service
        success = face_service.delete_face(request.face_id)

        if not success:
            return ApiResponseHelper.error(msg="人脸不存在或删除失败", code=500)

        return ApiResponseHelper.success(msg="删除成功")

    except Exception as e:
        app_logger.error(f"人脸删除接口异常: {e}", exc_info=True)
        return ApiResponseHelper.internal_error(msg="系统错误")


@router.get("/info/{face_id}")
async def get_face_info(face_id: str, include_deleted: bool = False):
    """
    获取人脸信息

    - **face_id**: 人脸ID
    - **include_deleted**: 是否包含已删除的记录（默认False）
    """
    try:
        app_logger.info(f"收到人脸信息查询请求: face_id={face_id}, include_deleted={include_deleted}")

        # 调用Service
        face_dto = face_service.get_face_info(face_id, include_deleted=include_deleted)

        if not face_dto:
            return ApiResponseHelper.error(msg="人脸不存在", code=500)

        return ApiResponseHelper.success(data=face_dto, msg="查询成功")

    except Exception as e:
        app_logger.error(f"人脸信息查询接口异常: {e}", exc_info=True)
        return ApiResponseHelper.internal_error(msg="系统错误")


@router.post("/rebuild-index")
async def rebuild_index():
    """重建FAISS索引"""
    try:
        app_logger.info("收到重建索引请求")

        success = face_service.rebuild_index()

        if not success:
            return ApiResponseHelper.error(msg="重建索引失败", code=500)

        return ApiResponseHelper.success(msg="重建索引成功")

    except Exception as e:
        app_logger.error(f"重建索引接口异常: {e}", exc_info=True)
        return ApiResponseHelper.internal_error(msg="系统错误")


@router.get("/statistics")
async def get_statistics():
    """获取统计信息"""
    try:
        stats = face_service.get_statistics()
        return ApiResponseHelper.success(data=stats, msg="查询成功")

    except Exception as e:
        app_logger.error(f"统计信息查询异常: {e}", exc_info=True)
        return ApiResponseHelper.internal_error(msg="系统错误")
